/**
 *  Copyright 2002-2009 the original author or authors.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package foo.bar.wiki.security;

import foo.bar.wiki.domain.User;
import foo.bar.wiki.services.ServicesUtil;
import foo.bar.wiki.services.UserExtendedWildcardPermissionService;
import foo.bar.wiki.utils.CollectionUtils;
import foo.bar.wiki.utils.Transformer;
import org.apache.shiro.SecurityUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * A {@link org.apache.shiro.authz.Permission} that could identify and auto-translate {@link org.apache.shiro.authz.Permission}
 * that contains the following as it's instance part.
 * <ul>
 *  <li>CURRENT_USER_BLOG_MEMBERSHIP_BLOG_IDS</li>
 *  <li>CURRENT_USER_BLOG_OWNERSHIP_BLOG_IDS</li>
 * </ul>
 *
 * Eg. with  <br/>
 *    blog:viewBlog:CURRENT_USER_BLOG_OWNERSHIP_BLOG_IDS<<br/>
 * and the current user is the owner of blog with id 1,2 and 3, the permission will get translated to<br/>
 *    blog:viewBlog:1,2,3
 *
 * <p/>
 * Essentially, domain part with
 *  CURRENT_USER_BLOG_MEMBERSHIP_BLOG_IDS
 * will get replace with the blog ids the current user is a member of.
 *  CURRENT_USER_BLOG_OWNERSHIP_BLOG_IDS
 * will get replace with the blog ids the current user is an owner of.
 *
 *
 * @author tmjee
 * @version $Date: 2009-03-15 23:53:19 +0800 (Sun, 15 Mar 2009) $ $Id$
 */
public class ExtendedWildcardPermission2 extends AbstractExtendedWildcardPermission {

    private static final Log LOG = LogFactory.getLog(ExtendedWildcardPermission2.class);


    private boolean caseSensitive = false;

    public static final String MEMBER_SPACE_ID = "MEMBER_SPACE_ID";
    public static final String OWNER_SPACE_ID = "OWNER_SPACE_ID";   
    public static final String OWN_USER_ID = "OWN_USER_ID";

    private UserExtendedWildcardPermissionService service;

    public ExtendedWildcardPermission2(String wildcardString) {
        super(wildcardString);
        this.service = ServicesUtil.getUserExtendedWildcardPermissionService();
    }

    public ExtendedWildcardPermission2(String wildcardString, boolean caseSensitive) {
        super(wildcardString, caseSensitive);
        this.caseSensitive = caseSensitive;
        this.service = ServicesUtil.getUserExtendedWildcardPermissionService();
    }

    public ExtendedWildcardPermission2(String wildcardString, UserExtendedWildcardPermissionService service) {
        super(wildcardString);
        this.service = service;
    }

    public ExtendedWildcardPermission2(String wildcardString, boolean caseSensitive, UserExtendedWildcardPermissionService service) {
        super(wildcardString, caseSensitive);
        this.service = service;
    }

    protected boolean canTranslate(ExtendedWildcardPermission p) {
        boolean result = (
            (p.getInstanceParts().size() > 0) &&
            (!p.getInstanceParts().contains(WILDCARD_TOKEN)) &&
            (
                (p.getInstanceParts().contains(caseSensitive ? MEMBER_SPACE_ID : MEMBER_SPACE_ID.toLowerCase())) ||
                (p.getInstanceParts().contains(caseSensitive ? OWNER_SPACE_ID : OWNER_SPACE_ID.toLowerCase())) ||
                (p.getInstanceParts().contains(caseSensitive ? OWN_USER_ID : OWN_USER_ID.toLowerCase()))
            )
        );
        return result;
    }

    protected ExtendedWildcardPermission translate(ExtendedWildcardPermission p) {
        Set<String> instancePart = new HashSet<String>(p.getInstanceParts());
        if (p.getInstanceParts().contains(caseSensitive ? MEMBER_SPACE_ID : MEMBER_SPACE_ID.toLowerCase())) {
            List<String> ids =service.getMemberSpaceId(((User) SecurityUtils.getSubject().getPrincipal()));
            instancePart.remove(caseSensitive ? MEMBER_SPACE_ID : MEMBER_SPACE_ID.toLowerCase());
            instancePart.addAll(ids);
        }
        if (p.getInstanceParts().contains(caseSensitive ? OWNER_SPACE_ID : OWNER_SPACE_ID.toLowerCase())) {
            List<String> ids = service.getOwnerSpaceId(((User) SecurityUtils.getSubject().getPrincipal()));
            instancePart.remove(caseSensitive? OWNER_SPACE_ID : OWNER_SPACE_ID.toLowerCase());
            instancePart.addAll(ids);
        }
        if (p.getInstanceParts().contains(caseSensitive ? OWN_USER_ID : OWN_USER_ID.toLowerCase())) {
            User self = (User)(SecurityUtils.getSubject().getPrincipal());
            String selfId = self.getId();
            instancePart.remove(caseSensitive ? OWN_USER_ID : OWN_USER_ID.toLowerCase());
            instancePart.add(selfId);
        }
        ExtendedWildcardPermission permission =  new ExtendedWildcardPermission(p.getDomainParts(), p.getActionParts(), instancePart);
        return permission;
    }


}
